package com.itheima.stock.service.impl;

import com.google.common.base.Strings;
import com.itheima.stock.constant.StockConstant;
import com.itheima.stock.mapper.SysUserMapper;
import com.itheima.stock.pojo.entity.SysUser;
import com.itheima.stock.service.UserService;
import com.itheima.stock.utils.IdWorker;
import com.itheima.stock.vo.req.LoginReqVo;
import com.itheima.stock.vo.resp.LoginRespVo;
import com.itheima.stock.vo.resp.R;
import com.itheima.stock.vo.resp.ResponseCode;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

// 创建当前类对象,并存放到IOC容器中
@Service
public class UserServiceImpl implements UserService {

    // 注入mapper层的对象
    @Autowired
    private SysUserMapper sysUserMapper;
    // 密码校验器
    @Autowired
    private PasswordEncoder passwordEncoder;
    // 雪花算法工具
    @Autowired
    private IdWorker idWorker;
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 生成验证码
     * @return
     */
    @Override
    public R<Map> getCaptchaCode() {
        //生成验证码
        String checkCode = RandomStringUtils.randomNumeric(4);
        //将验证码存放到redis中
        String redisKey = idWorker.nextId()+"";
        ValueOperations ops = redisTemplate.opsForValue();
        // 往redis中存放验证码并设置存活时间
        //ops.set(redisKey,checkCode,60, TimeUnit.SECONDS);
        ops.set(StockConstant.CHECK_PREFIX+redisKey,checkCode,60, TimeUnit.SECONDS);
        //封装返回结果
        HashMap<String, String> map = new HashMap<>();
        map.put("code",checkCode);
        map.put("rkey",redisKey);
        return R.ok(map);
    }

    /**
     * 用户登陆功能
     * @param vo
     * @return
     */
    @Override
    public R<LoginRespVo> login(LoginReqVo vo) {
        //todo:校验验证码
        if (vo==null || Strings.isNullOrEmpty(vo.getCode()) || Strings.isNullOrEmpty(vo.getRkey())){
            return R.error(ResponseCode.CHECK_CODE_NOT_EMPTY.getMessage());
        }
        //从redis中获取生成的验证码
        ValueOperations ops = redisTemplate.opsForValue();
        String ckcode = (String) ops.get(StockConstant.CHECK_PREFIX + vo.getRkey());
        //获取用户输入的验证码
        String code = vo.getCode();
        // 不为空的字符串放到前面
        if (!code.equalsIgnoreCase(ckcode)){
            return R.error(ResponseCode.CHECK_CODE_ERROR.getMessage());
        }
        //0.判断请求参数是否为空
        if (Strings.isNullOrEmpty(vo.getUsername()) || Strings.isNullOrEmpty(vo.getPassword())){
            return R.error(ResponseCode.DATA_ERROR.getMessage());
        }
        //1.根据用户名查询用户详情
        SysUser sysUser = getUserByUserName(vo.getUsername());
        if (sysUser==null){
            return R.error(ResponseCode.USERNAME_OR_PASSWORD_ERROR.getMessage());
        }
        //2.校验用户密码
        // 明文密码
        String pwd = vo.getPassword();
        // 密文密码
        String password = sysUser.getPassword();
        // 验证
        boolean flag = passwordEncoder.matches(pwd, password);
        // 密码不正确
        if (!flag){
            return R.error(ResponseCode.USERNAME_OR_PASSWORD_ERROR.getMessage());
        }
        // 封装登陆成功的用户信息
        LoginRespVo respVo = new LoginRespVo();
//        respVo.setId(sysUser.getId()+"");
//        respVo.setUsername(sysUser.getUsername());
//        respVo.setPhone(sysUser.getPhone());
//        respVo.setNickName(sysUser.getNickName());
        // todo:属性名称与类型必须相同，否则copy不到
        BeanUtils.copyProperties(sysUser,respVo);
        return R.ok(respVo);
    }

    /**
     * 根据用户名查询用户详情
     * @param userName 用户名称
     * @return
     */
    @Override
    public SysUser getUserByUserName(String userName) {
        SysUser sysUser = sysUserMapper.findByUserName(userName);
        return sysUser;
    }
}
